import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.gui.StackWindow;
import ij.process.ImageProcessor;

import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;


public class MontageSettings {
	static String slash ="\\";
	ImageStack vS;
	JPanel panel, topPanel, midPanel;
	InstructionPanel instrPanel;
	 File folder, gen1File;
	 int mode;
	
	 GridBagConstraints c;
	 JButton gen1Button;
	JLabel gen1Label;
	 String[] tokens, folderList;
	ArrayList<String> channelList;
	JTextArea xColTA, yRowTA;
	Checkbox[] chBox;
	String header = "Pos_";
	String basename = "";
	String basetime = "0000000000";
	String subString;
	String z="000";
	String t="000000000";
	String lastZIndex =z;
	String lastTimeIndex=t;
	String basetype;

	JTextArea xOTA, yOTA,xSTA,ySTA,xETA,yETA;
	
	ImagePlus imp,montage;
	int width, height, zDepth,counter, xStart, xEnd, yStart, yEnd;
	
	public MontageSettings(JPanel montageSettingsP,
		InstructionPanel iP){
		instrPanel = iP;
		panel = montageSettingsP;
		panel.removeAll();
		panel.setLayout(new BorderLayout());
	}
	public void fillMenu(File f, int selectedIndex) {
		panel.removeAll();
		topPanel = new JPanel();
		midPanel = new JPanel();
		panel.add(topPanel,BorderLayout.NORTH);
		panel.add(midPanel, BorderLayout.CENTER);
		midPanel.setLayout(new GridBagLayout());
		c = new GridBagConstraints();
		instrPanel.setPrompt("");
		folder =f;
		mode = selectedIndex;
		channelList = new ArrayList<String>();
		
		folderList = folder.list();
		switch (mode){
		case 0://Gen1
			topPanel.setLayout(new GridLayout(1,2));
			gen1Button = new JButton("Select First File");
			gen1Label = new JLabel("None Selected");
			topPanel.add(gen1Button);
			topPanel.add(gen1Label);
			instrPanel.setHeader("Gen1 Montage");
			String s1 ="Step 1: Select first file of acq. data";
			String s2 ="Step 2:Input dimensions of montage";
			String s3 ="Step 3: Select channels for montage";
			String s4 ="Step 4: Refresh Preview will create ";
			String s5 ="      a new window with current settings";
			instrPanel.setInstructions(s1+"\n"+s2+"\n"+s3+"\n"+"\n"+s4+"\n"+s5);
			
			gen1Button.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e){
					JFileChooser chooser = new JFileChooser(folder.getAbsolutePath());
					chooser.setDialogTitle("Choose first file of acquisition");
					chooser.showOpenDialog(null);
					File firstFile = chooser.getSelectedFile();
					gen1Label.setText(firstFile.getAbsolutePath());
					tokens = firstFile.getName().split("_");
					basename = tokens[0];
					basetime = tokens[3].substring(1,tokens[3].length()-4);
					t= basetime;
					//Get dimensions
					ImagePlus imp = IJ.openImage(firstFile.getAbsolutePath());
					zDepth = imp.getNSlices();
					width= imp.getWidth();
					height = imp.getHeight();
					String lastPosIndex, channel;
					String Pos = "0";			
					for(int i=0; i<folderList.length;i++){
						if(folderList[i].contains(basename)){
							tokens = folderList[i].split("_");
							if(tokens.length==4){
								lastPosIndex = tokens[2].substring(1,tokens[2].length()-1);
								channel = tokens[1];
								lastTimeIndex = tokens[3].substring(1,tokens[3].length()-4);
								if(!channelList.contains(channel)){
									channelList.add(channel);
								}if(lastPosIndex.compareTo(Pos)>0){
									Pos =  lastPosIndex;
								}if(lastTimeIndex.compareTo(t)>0){
									t =  lastTimeIndex;
								}
							}
						}
					}
					xColTA= new JTextArea(1,1);
					xColTA.setSize(1, 1);
					yRowTA = new JTextArea(1,1);
					yRowTA.setSize(1,1);
					c.gridx =1;
					c.gridy =0;
					c.gridwidth =1;
					midPanel.add(new JLabel("Grid Size"),c);
					c.gridx =0;
					c.gridy++;
					midPanel.add(xColTA,c);
					c.gridx++;
					midPanel.add(new JLabel("x",JLabel.CENTER),c);
					c.gridx++;
					midPanel.add(yRowTA,c);
					c.gridy++;
					c.gridx = 1;
					midPanel.add(new JLabel("Select Channels"),c);
					c.gridy++;
					chBox = new Checkbox[channelList.size()+1];
					chBox[0] = new Checkbox("All Channels",true);
					midPanel.add(chBox[0],c);
					for (int i=1;i<=channelList.size();i++){
						c.gridy++;
						chBox[i]= new Checkbox(channelList.get(i-1),false);
						midPanel.add(chBox[i],c);
					}
					midPanel.validate();
				}
			});
			break;
		case 1: case 3://Grids
			String s21 = "Montage Grids";
			String s22 = "Step 1: Select channels to montage";
			String s23 = "Step 2: Refresh Preview will open montage in new Window";
			String s24 = "To abort Saving, please kill process";
			instrPanel.setInstructions(s21+"\n"+s22+"\n"+s23+"\n"+s24);
			File searchFolder= new File(folder.getAbsolutePath(),"Grid_0_0");
			counter=0;						
			String searchGrid = "Grid_0_0";
			boolean found = true;
			//must be a nxn grid
			while (found){
				found = false;
				for (int i=0;i<folderList.length;i++){			
					if((folderList[i].compareTo(searchGrid)==0)){
						found = true;
						counter++;	
						break;
					}
				}
				searchGrid = "Grid_"+counter+"_"+counter;
			}
			if (counter == 0){
				//Error
				instrPanel.setPrompt("Error: Grid Folder is not in the correct Format");
				return;
			}
			searchFolder = new File(folder.getAbsolutePath(),"Grid_0_0");
			String[] searchList = searchFolder.list();
			String subString, lastZIndex;
			//Traverses folders to get dimensions
			for(int i=0; i<searchList.length;i++){
				if(searchList[i].contains("img")){
					tokens =searchList[i].split("_");
					subString = tokens[2];
					lastZIndex = tokens[3];
					lastTimeIndex = tokens[1];
					if(!channelList.contains(subString)){
						channelList.add(subString);
					}if(lastZIndex.compareTo(z)>0){
						z =  lastZIndex;
					}if(lastTimeIndex.compareTo(t)>0){
						t =  lastTimeIndex;
					}
				}
			}//Prompt user to select channels	
			c.gridx=0;
			c.gridy=0;
			midPanel.add(new JLabel("Select Channels"),c);
			chBox = new Checkbox[channelList.size()+1];
			chBox[0] = new Checkbox("All Channels",true);
			c.gridy++;
			midPanel.add(chBox[0],c);
			for (int i=1;i<=channelList.size();i++){
				c.gridy++;
				chBox[i]= new Checkbox(channelList.get(i-1),false);
				midPanel.add(chBox[i],c);
			}
			midPanel.validate();
			//get frame size
			ImagePlus imp = IJ.openImage(folder.getAbsolutePath()+slash+"Grid_0_0"+slash+"img_000000000_"+channelList.get(0)+"_000.tif");
			width = imp.getWidth();
			height = imp.getHeight();
			zDepth = Integer.parseInt(z.substring(0,3));
			c.gridx = 0;
			c.gridy++;
			midPanel.add(new JLabel("Overlaps"),c);
			xOTA = new JTextArea(2,1);
			xOTA.setText("0");
			c.gridy++;
			midPanel.add(new JLabel("X"),c);
			c.gridx++;
			midPanel.add(xOTA,c);
			yOTA = new JTextArea(2,1);
			yOTA.setText("0");
			c.gridy++;
			c.gridx=0;
			midPanel.add(new JLabel("Y"),c);
			c.gridx++;
			midPanel.add(yOTA,c);
			break;
		case 2: case 4://Pos
			String s31 = "Montage Positions";
			String s32 = "Step 1: Input starting and ending points";
			String s33 = "Step 2: Select channels to montage";
			String s34 = "Step 3: Refresh Preview to open new montage window";
			instrPanel.setInstructions(s31+"\n"+s32+"\n"+s33+"\n"+s34);
			found = false;
			int j =0;			
			while(!found&&(folderList.length>j)){
				if(folderList[j].contains("Pos")){
					found = true;
				}else{
					j++;
				}
			}
			if (!found){
				instrPanel.setPrompt("Error: Folder is not in the correct Format");
				return;
			}		
			tokens = folderList[j].split("_");
			header = tokens[0];
			searchFolder = new File(folder.getAbsolutePath(),folderList[j]);
			searchList = searchFolder.list();
			//Get dimensions			
			for(int i=0; i<searchList.length;i++){
				if(searchList[i].contains("img")){
					tokens = searchList[i].split("_");
					subString = tokens[2];
					lastZIndex = tokens[tokens.length-1];
					lastTimeIndex = tokens[1];
					if(!channelList.contains(subString)){
						channelList.add(subString);
					}if(lastZIndex.compareTo(z)>0){
						z =  lastZIndex;
					}if(lastTimeIndex.compareTo(t)>0){
						t =  lastTimeIndex;
					}
				}
			}
			//Prompt user for size/channels to montage
			c.gridx = 0;
			c.gridy =0;
			midPanel.add(new JLabel("Dimensions"),c);
			c.gridy++;
			midPanel.add(new JLabel("xStart"),c);
			c.gridx++;
			xSTA= new JTextArea(2,2);
			xSTA.setText("0");
			midPanel.add(xSTA,c);
			c.gridx++;
			midPanel.add(new JLabel("xEnd"),c);
			c.gridx++;
			xETA= new JTextArea(2,2);
			xETA.setText("2");
			midPanel.add(xETA,c);
			c.gridx = 0;
			c.gridy++;
			midPanel.add(new JLabel("yStart"),c);
			c.gridx++;
			ySTA= new JTextArea(2,2);
			ySTA.setText("0");
			midPanel.add(ySTA,c);
			c.gridx++;
			midPanel.add(new JLabel("yEnd"),c);
			c.gridx++;
			yETA= new JTextArea(2,2);
			yETA.setText("2");
			midPanel.add(yETA,c);
			c.gridx =0;
			c.gridy++;
			midPanel.add(new JLabel("Select Channels"),c);
			chBox = new Checkbox[channelList.size()+1];
			chBox[0] = new Checkbox("All Channels",true);
			c.gridy++;
			midPanel.add(chBox[0],c);
			for (int i=1;i<=channelList.size();i++){
				c.gridy++;
				chBox[i]= new Checkbox(channelList.get(i-1),false);
				midPanel.add(chBox[i],c);
			}
			midPanel.validate();
			imp = IJ.openImage(searchFolder.getAbsolutePath()+slash+searchList[searchList.length/2]);
			width = imp.getWidth();
			height = imp.getHeight();
			imp.flush();
			zDepth = Integer.parseInt(z.substring(0,3));
			c.gridx = 0;
			c.gridy++;
			midPanel.add(new JLabel("Overlaps"),c);
			xOTA = new JTextArea(2,1);
			xOTA.setText("0");
			c.gridy++;
			midPanel.add(new JLabel("X"),c);
			c.gridx++;
			midPanel.add(xOTA,c);
			yOTA = new JTextArea(2,1);
			yOTA.setText("0");
			c.gridy++;
			c.gridx=0;
			midPanel.add(new JLabel("Y"),c);
			c.gridx++;
			midPanel.add(yOTA,c);
			break;
		}
		
		
	}
	public void create(){
		//which channels selected]
		ArrayList<String> cLCopy = new ArrayList<String>();
		if(chBox[0].getState()){
			for(int i=1;i<= channelList.size();i++){
				cLCopy.add(channelList.get(i-1));
			}
		}else{
			for(int i=1;i<= channelList.size();i++){
				if (chBox[i].getState()){
					cLCopy.add(channelList.get(i-1));
				}
			}
		}
		switch(mode){
		case 0:
			int xEnd = Integer.parseInt(xColTA.getText());
			int yEnd = Integer.parseInt(yRowTA.getText());
			vS = new Gen1( xEnd,yEnd,width, height, zDepth, cLCopy, folder, basename, basetime,t);
			break;
		case 1: 
			vS = new Gen2( counter-1,xOTA.getText(),yOTA.getText(),width, height, zDepth, cLCopy, folder, t);			
			break;
		case 2:
			//axis is swapped
			xStart = Integer.parseInt(ySTA.getText());
			yStart  = Integer.parseInt(xSTA.getText());
			xEnd= Integer.parseInt(yETA.getText());
			yEnd = Integer.parseInt(xETA.getText());
			vS =new Gen2(xStart, xEnd,yStart, yEnd,header,xOTA.getText(),yOTA.getText(),
					width, height, zDepth, cLCopy, folder, t);
			break;
		case 3: 
			vS=new Gen3( counter-1,xOTA.getText(),yOTA.getText(),width, height, zDepth, cLCopy, folder, t);
			break;
		case 4: 
			xStart = Integer.parseInt(ySTA.getText());
			yStart  = Integer.parseInt(xSTA.getText());
			xEnd= Integer.parseInt(yETA.getText());
			yEnd = Integer.parseInt(xETA.getText());
			vS =new Gen3(xStart, xEnd,yStart, yEnd,header,xOTA.getText(),yOTA.getText(),
					width, height, zDepth, cLCopy, folder, t);
			break;
		default:
			break;
		}
		montage = new ImagePlus("",vS);
		montage.setDimensions(cLCopy.size(), zDepth,vS.getSize()/(cLCopy.size()*zDepth));
		montage.setOpenAsHyperStack(true);
		new StackWindow(montage);
		
	}
	public void save(File sF){
		ImagePlus saveImp;
		saveImp = new ImagePlus("",montage.getProcessor());
		for(int t =1;t<=montage.getNFrames();t++){
			for(int ch =1;ch<=montage.getNChannels();ch++){
				String savePath = sF.getAbsolutePath()+slash+"montage"+"_"+channelList.get(ch-1)+"_"+String.format("%03d",t);
				ImageProcessor p1= montage.getProcessor();
				ImageStack saveStack = new ImageStack(p1.getWidth(),p1.getHeight());
				for(int z =1;z<=montage.getNSlices();z++){
					montage.setPosition(ch,z,t);
					saveStack.addSlice("",montage.getProcessor());
				}
				saveImp.setStack(saveStack);	
				IJ.saveAs(saveImp,"tif",savePath);
			}
		}
		
	}
	public void toStack(){
		ImageProcessor p = montage.getProcessor();
		ImageStack realStack = new ImageStack(p.getWidth(),p.getHeight());
		for(int i =1;i<=montage.getStackSize();i++){
			montage.setPosition(i);
			realStack.addSlice("",montage.getProcessor());
		}
		ImagePlus realImp = new ImagePlus("",realStack); 
		realImp.setDimensions(montage.getNChannels(), montage.getNSlices(), montage.getNFrames());
		realImp.setOpenAsHyperStack(true);
		new StackWindow(realImp);
		montage.close();
	}
}